package forumSystem;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import javax.mail.MessagingException;
import javax.mail.internet.AddressException;

import net.sf.classifier4J.ClassifierException;
import net.sf.classifier4J.SimpleClassifier;
import net.sf.classifier4J.bayesian.BayesianClassifier;
import net.sf.classifier4J.bayesian.IWordsDataSource;
import net.sf.classifier4J.bayesian.SimpleWordsDataSource;
import net.sf.classifier4J.bayesian.WordsDataSourceException;

import msgParser.Functions;
import msgParser.Strings;
import reactor.Reactor;

public class ForumSystemImpl implements ForumSystem
{
	private static String ErrorMsg;
	private static String[] Curses=loadCurses();
	private static Vector<Vector<String>> pendingUsers = new Vector<>();


	public static String[] loadCurses()
	{
		String ans[]=null;
		try{
			BufferedReader reader = new BufferedReader( new FileReader ("Eng_Curses"));
			String         line = null;
			StringBuilder  stringBuilder = new StringBuilder();
			String         ls = System.getProperty("line.separator");

			while( ( line = reader.readLine() ) != null ) {
				stringBuilder.append( line );
				stringBuilder.append( ls );
			}
			String file = stringBuilder.toString();
			ans= file.split("\\s");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return ans;
	}
	public static int createForum(String forumTitle, int adminID, int policyID, TreeMap<String, String> session) {
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && session.get("userID").equals(superAdminid))
		{
			int forumID=Reactor.db.addForumWithManager(forumTitle, "no need for description", adminID, policyID);


			if(forumID!=-1)
			{
				return forumID;
			}
			else
			{
				ErrorMsg="Cannot add forum - Error in db";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Cannot add forum - Not a super admin";
			return -1;
		}

	}

	public static String getLastErrormsg() {
		return ErrorMsg;
	}



	public static int logOut(TreeMap<String, String> session) {
		String ID = session.get("userID");
		if(ID == null)
		{
			ErrorMsg="Logout error - Only logged in members can logout";
			return -1;
		}
		else
		{
			int id = Integer.valueOf(ID);
			session.remove("isOnline");
			session.remove("userID");
			return id;
		}
	}


	public static int[] logIn(String username, String pass, int forumID, TreeMap<String, String> session) {
		int[] ans=new int[2];
		if(session.get("isOnline")!=null && session.get("isOnline").equals("true"))
		{
			ErrorMsg="Login error - You are already logged in";
			return null;
		}
		else if(Reactor.db.isUserExist(username, pass, forumID))
		{
			int userID=Reactor.db.getUserByUserName(username).getId();
			session.put("isOnline", "true");
			session.put("userID", String.valueOf(Reactor.db.getUserByUserName(username).getId()));
			ans[0]=Reactor.db.getUserByUserName(username).getId();
			ans[1]=Reactor.db.getUserRank(ans[0]);
			return ans;
		}
		else
		{
			ErrorMsg="Login error - Wrong username or password";
			return null;
		}
	}

	public static int initForum(String superAdminUserName, String SuperAdminPass) {
		try
		{
			Reactor.db.initialize(superAdminUserName, SuperAdminPass);
			return 1;
		}
		catch(Exception e)
		{
			ErrorMsg="cant initialize Forum";
			return -1;
		}
	}

	private static boolean isEmailValid (String email){
		return (email.contains("@") && email.contains("."));
	}
	
	public static int register(String userName, String password, String mail, int targetForum, TreeMap<String, String> session) {
		int userID=-1;
		
		if(session.get("isOnline")!=null && session.get("isOnline").equals("true"))
		{
			ErrorMsg="Register Error - Logged in users cannot register";
			return userID;
		}

		Forum forum = Reactor.db.getForumByID(targetForum);
		if (forum == null){
			ErrorMsg="Register Error - forumID is invalid";
			return userID;
		}
			
		ForumPolicy fp = Reactor.db.getPolicyByID(forum.getPolictyID());
		int securityPolicy = fp.getSecurityPolicy();
		System.out.println("heyhey"+securityPolicy);
		if (!isEmailValid(mail)){
			ErrorMsg="Register Error - Email is invalid";
			return userID;
		}

		if (securityPolicy == Strings.VALID_EMAIL_SECURITY) 
		{
			if(!isMailInUse(mail, targetForum))
			{
				userID=Reactor.db.addUser(userName, password,mail, targetForum);
			}
			else
			{
				ErrorMsg="Email is used by another user";
				return -1;
			}
				
		}
		else if (securityPolicy == Strings.CODE_AUTHEN_SECURITY) {
			String code = Functions.mailHash(userName + password + mail);
			Vector<String> user = new Vector<String>();
			user.add(userName);
			user.add(password);
			user.add(mail);
			user.add(targetForum+"");
			user.add(code);
			pendingUsers.add(user);
			try {
				Functions.sendMail(mail, "SE FORUMS - Code authentication", 
						"Hi there ! \n Please copy the code below: \n" + code);
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			userID =-2;
			return userID;
		}
		else
			userID=Reactor.db.addUser(userName, password,mail, targetForum);
		
		if(userID!=-1)
		{
			return userID;
		}
		else
		{
			ErrorMsg="Cannot register this user";
			return userID;
		}
	}

	public static int createSubForum(String subforumtitle, int parentForumID, int moderatorID, TreeMap<String, String> session) {
		int forumid=parentForumID;
		Forum forum = Reactor.db.getForumByID(forumid);
		if (forum == null){
			ErrorMsg="Cannot add subForum - invalid parentForumID";
			return -1;
		}
			
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==forum.getAdminID() 
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			int subForumID=Reactor.db.addSubForum(subforumtitle,
					"description not needed for now", 
					parentForumID, moderatorID);
			//Reactor.db.addManagerToForum(argInt, argInt2);
			if(subForumID!=-1)
			{
				return subForumID;
			}
			else
			{
				ErrorMsg="Cannot add subForum - Error in db";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Cannot add subforum - You do not have the right permissions";
			return -1;
		}
	}
	/**
	public static int createTopic(String title, String TopicBody, int parentSubForumID, TreeMap<String, String> session) {
		if(session.get("userID")==null)
		{
			ErrorMsg="newMessageError only loggedin members can add message";
			return -1;
		}
		else
		{
			int postID=Reactor.db.addPost(Integer.parseInt(session.get("userID")), 
					parentSubForumID, 
					title, 
					TopicBody);
			if(postID!=-1)
			{
				return postID;
			}
			else
			{
				ErrorMsg="newMessageError error in db";
				return -1;
			}
		}
	}
	 **/
	public static int getNumOfTopicsAndReplies(int subForum)
	{
		int acc = 0;
		Vector<Post> posts=Reactor.db.getSubForumPosts(subForum);
		for (int i=0; i<posts.size(); i++)
		{
			Vector<Reply> replies = Reactor.db.getPostReplies(posts.get(i).getId());
			acc = acc + replies.size();
		}
		return acc+posts.size();
	}

	public static double CheckCurses(String toCheck)
	{
		double dClassification = 0.0;

		SimpleClassifier classifier = new SimpleClassifier();

		for (int i=0; i<Curses.length; i++ )
		{
			classifier.setSearchWord(Curses[i]);
			dClassification = classifier.classify(toCheck);
			if (dClassification == 1.0) {System.out.println(toCheck);return dClassification;};
		}
		return dClassification;
	}


	public static int createTopic(String title, String TopicBody, int parentSubForumID, TreeMap<String, String> session) throws AddressException, MessagingException {
		int postID = 0;
		File f= null;
		File f2 =null;
		SubForum SubForumToGetPolicy=Reactor.db.getSubForumByID(parentSubForumID);
		Forum forumToGetPolicy=Reactor.db.getForumByID(SubForumToGetPolicy.getParentForum());
		ForumPolicy fp=Reactor.db.getPolicyByID(forumToGetPolicy.getPolictyID());

		if(session.get("userID")==null)
		{
			ErrorMsg="Only logged in members can add message";
			return -1;
		}
		else
		{
			int threshold = getNumOfTopicsAndReplies(parentSubForumID);
			//not enough messages to activate classifier yet
			System.out.println(threshold);
			String toCheck = title+" "+TopicBody;
			if (CheckCurses(toCheck) == 1.0) {postID = -2;System.out.println("heyheyhey");}                          
			
			else
			{
			//above 20 messages in subforum so activate the classifier
			if(threshold>20)
			{
				f = new File("Matches"+ parentSubForumID +".txt");
				f2 = new File("NonMatches"+ parentSubForumID +".txt");

				String Appender = "";
				String Appender2 = "";
				double dreturn;
				IWordsDataSource wds = new SimpleWordsDataSource();

				if(!f.exists())         //this is the first time we've crossed "the over 20 messages" mark
				{
					Vector<Post> posts=Reactor.db.getSubForumPosts(parentSubForumID);
					for (int k=0; k<posts.size(); k++)
					{
						Appender = Appender + posts.get(k).getDesc()+" ";
						Vector<Reply> r=Reactor.db.getPostReplies(posts.get(k).getId());
						for (int i=0; i<r.size(); i++)
							Appender = Appender + r.get(i).getContent()+" ";
					}
					try
					{
						f.createNewFile();                  
						PrintWriter out = new PrintWriter(f);
						out.println(Appender);
						out.close();
					}
					catch (IOException e) {e.printStackTrace();}
				}
				try{
					if (!f2.exists()) f2.createNewFile(); 
				}
				catch (IOException e) {e.printStackTrace();}

				try{
					BufferedReader reader = new BufferedReader( new FileReader ("Matches"+ parentSubForumID +".txt"));
					String         line = null;
					StringBuilder  stringBuilder = new StringBuilder();
					String         ls = System.getProperty("line.separator");

					while( ( line = reader.readLine() ) != null )
					{
						stringBuilder.append( line );
						stringBuilder.append( ls );
					}
					String file1 = stringBuilder.toString();
					Appender = file1;
				}
				catch (IOException e) {e.printStackTrace();}
				try{
					BufferedReader reader = new BufferedReader( new FileReader ("NonMatches"+ parentSubForumID +".txt"));
					String         line = null;
					StringBuilder  stringBuilder = new StringBuilder();
					String         ls = System.getProperty("line.separator");

					while( ( line = reader.readLine() ) != null )
					{
						stringBuilder.append( line );
						stringBuilder.append( ls );
					}
					String file1 = stringBuilder.toString();
					Appender2 = file1;
				}
				catch (IOException e) {e.printStackTrace();}

				String[] training = Appender.split("\\s");
				String[] training2 = Appender2.split("\\s");
				for (int n=0; n<training.length; n++)
					try {
						wds.addMatch(training[n]);
					} catch (WordsDataSourceException e) {e.printStackTrace();}
				for (int n=0; n<training2.length; n++)
					try {
						wds.addNonMatch(training2[n]);
					} catch (WordsDataSourceException e) {e.printStackTrace();}

				BayesianClassifier BC = new BayesianClassifier(wds);
				try {
					dreturn = BC.classify(title+" "+TopicBody);
					if (dreturn < 0.8)
					{
						postID = -3;
						String t = title+" "+TopicBody;
						//      String[] badExample = t.split("\\s");
						FileWriter fw = new FileWriter("NonMatches"+ parentSubForumID +".txt", true);
						fw.write(t);
						fw.close();
					}
				}
				catch (IOException e) {e.printStackTrace();}
				catch (WordsDataSourceException e) {e.printStackTrace();}
				catch (ClassifierException e) {e.printStackTrace();}

			}
			
			}
			if((fp.getBadWordsPolicy() & Strings.INFORM_MODERATOR_BAD_WORDS) != 0  && postID == -2)
			{
				Vector<Integer> mod=Reactor.db.getSubForumModerators(parentSubForumID);
				String titleToSend="Message with filthy language in your forum";
				String contentToSend="Dear moderator \n the message : \n\n"+TopicBody+" \n wants to be published in your forum. \n just letting you know.";
				String mail;
				for (int i = 0; i < mod.size(); i++) {
					User modTemp = Reactor.db.getUserByID(mod.get(i));
					if (modTemp != null ) {
						mail=modTemp.getMail();
						Functions.sendMail(mail, titleToSend, contentToSend);
					}
				}
			}
			if(postID > -1)
			{
				postID=Reactor.db.addPost(Integer.parseInt(session.get("userID")),
						parentSubForumID,
						title,
						TopicBody);    
				return postID;
			}
			
			else if((fp.getBadWordsPolicy() & Strings.REJECT_BAD_WORDS) == 0  && postID == -2)
			{
				postID=Reactor.db.addPost(Integer.parseInt(session.get("userID")),
						parentSubForumID,
						title,
						TopicBody);    
				return postID;
			}
			else
			{
				if (postID == -1) ErrorMsg="New Message Error - Error in db";
				if (postID == -2) ErrorMsg="Message contains forbidden words";
				if (postID == -3) ErrorMsg="Message isn't related to subforum topic";
				return -1;
			}
		}
	}

	public static int createReply(String replyBody, int TopicID, TreeMap<String, String> session) throws AddressException, MessagingException {
		if(session.get("userID")==null)
		{
			ErrorMsg= "New Reply Error ; Only logged in members can add message";
			return -1;
		}

		else
		{
			int flag = 0;
			int fID=Reactor.db.getForumIdByTopicId(TopicID);
			Forum f=Reactor.db.getForumByID(fID);
			ForumPolicy fp=Reactor.db.getPolicyByID(f.getPolictyID());
			int replyID;
			
			
			
			String toCheck = replyBody;
			if (CheckCurses(toCheck) == 1.0) flag = -2;
			
			if((fp.getBadWordsPolicy() & Strings.INFORM_MODERATOR_BAD_WORDS) != 0  && flag == -2)
			{
				int subForumID=Reactor.db.getSubForumIdByTopicId(TopicID);
				Vector<Integer> mod=Reactor.db.getSubForumModerators(subForumID);
				String titleToSend="Reply with filthy language in your forum";
				String contentToSend="Dear moderator \n the message : \n\n"+replyBody+" \n wants to be published in your forum. \n just letting you know.";
				String mail;
				for (int i = 0; i < mod.size(); i++) {
					System.out.println(titleToSend);
					System.out.println(contentToSend);
					mail=Reactor.db.getUserByID(mod.get(i)).getMail();
					System.out.println(mail);
					Functions.sendMail(mail, titleToSend, contentToSend);
				}
			}
			
			if(((fp.getBadWordsPolicy() & Strings.REJECT_BAD_WORDS) == 0  && flag == -2) || flag!=-2)
			{
				replyID=Reactor.db.addReply(Integer.parseInt(session.get("userID")), 
						TopicID, 
						replyBody);
				return replyID;
			}
			else
			{
				ErrorMsg="Cannot add reply - Error in db";
				return -1;
			}
		}
	}


	public static Vector<String> getAllForumsWithIDs() {
		Vector<Forum> forumlist=Reactor.db.getForumlist();
		Vector<String> ans=new Vector<String>();
		if(forumlist!=null)
		{
			for (int i = 0; i < forumlist.size(); i++) {
				ans.add(forumlist.get(i).getName());
				ans.add(Integer.valueOf(forumlist.get(i).getId()).toString());
			}
			return ans;
		}
		else
		{
			ErrorMsg="Error in forum list";
			return null;
		}
	}

	public static Vector<String> getAllSubForums(int ForumID) {
		int forumID=ForumID;
		Vector<SubForum> posts=Reactor.db.getSubForumslist(forumID);
		Vector<String> ans= new Vector<String>();
		if(posts!=null)
		{
			for (int i = 0; i < posts.size(); i++) {
				ans.add(posts.get(i).getTitle());
				ans.add(Integer.valueOf(posts.get(i).getId()).toString());
			}
			return ans;
		}
		else
		{
			ErrorMsg="sub forums - Error in db";
			return null;
		}
	}

	public static int getSubForumPostCount(int subforumid)
	{
		Vector<Post> posts=Reactor.db.getSubForumPosts(subforumid);
		return posts!=null?posts.size():-1;
	}


	public static Vector<String> getAllTopicsInSubForum(int subForumID) {
		int forumID=subForumID;
		Vector<String> ans= new Vector<String>();
		Vector<Post> posts=Reactor.db.getSubForumPosts(forumID);
		if(posts!=null)
		{
			for (int i = 0; i < posts.size(); i++) {
				ans.add(posts.get(i).getTitle());
				ans.add(Integer.valueOf(posts.get(i).getId()).toString());
			}
			return ans;
		}
		else
		{
			ErrorMsg="Topics - Error in db";
			return null;
		}
	}

	public static Vector<String> getAllUsers(TreeMap<String, String> session) {
		Vector<String> ans= new Vector<String>();
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && session.get("userID").equals(superAdminid))
		{
			Vector<User> userList=Reactor.db.getUsers();
			if(userList!=null)
			{
				for (int i = 0; i < userList.size(); i++) {
					ans.add(userList.get(i).getUsername());
					ans.add(Integer.valueOf(userList.get(i).getId()).toString());
				}
				return ans;
			}
			else
			{
				ErrorMsg="No forums";
				return null;
			}
		}
		else
		{
			ErrorMsg="you cannot do that";
			return null;
		}
	}

	public static Vector<String> getAllMessages(int TopicID) {
		int postID=TopicID;
		Vector<String> ans = new Vector<String>();
		Post p=Reactor.db.getPostByID(postID);
		if(p!=null)
		{
			//ans.add(p.getTitle());
			ans.add(p.getDesc());
			ans.add(p.getId()+"");
			ans.add(Integer.valueOf(p.getUserID()).toString());
			ans.add(Reactor.db.getUserByID(p.getUserID()).getUsername());
			Vector<Reply> r=Reactor.db.getPostReplies(p.getId());
			for (int i = 0; i < r.size(); i++) {
				ans.add(r.get(i).getContent());
				ans.add(r.get(i).getId()+"");
				ans.add(Integer.valueOf(r.get(i).getUserID()).toString());
				ans.add(Reactor.db.getUserByID(r.get(i).getUserID()).getUsername());
			}
			return ans;
		}
		else
		{
			ErrorMsg="Ileagal post";
			return null;
		}
	}

	public static int getSubForumPostPlusRepliesCount(int subForumId)
	{
		Vector<Post> posts=Reactor.db.getSubForumPosts(subForumId);
		int counter=0;
		for (Post p: posts) {
			counter+=Reactor.db.getPostReplies(p.getId()).size()+1;
		}
		return counter;
	}

	public static int removeTopic(int TopicID, TreeMap<String, String> session) {
		int subforumID=Reactor.db.getSubForumIdByTopicId(TopicID);
		int forumID=Reactor.db.getForumIdByTopicId(TopicID);
		if(forumID<=0)
		{
			ErrorMsg="Topic not exists";
			return -1;
		}
		Forum forumToPolicy=Reactor.db.getForumByID(forumID);
		if(subforumID<=0 || forumID<= 0 || forumToPolicy == null)
		{
			ErrorMsg="Topic not exists";
			return -1;
		}
		ForumPolicy fp=Reactor.db.getPolicyByID(forumToPolicy.getPolictyID());
		

		if(session.get("userID")!=null && 
				((Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() && (fp.getDeletePostPermission() & Strings.ADMIN_FORUM_DELETE_POST)!=0 )
						||
						(Reactor.db.isModerator(Integer.parseInt(session.get("userID")), subforumID)==1 && (fp.getDeletePostPermission() & Strings.MODERATOR_DELETE_POST)!=0)
						||
						//(Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId())) && (fp.getDeletePostPermission() & Strings.AUTHOR_FORUM_DELETE_POST)!=0 )
			(Integer.parseInt(session.get("userID"))==Reactor.db.getPostByID (TopicID).getUserID()) && (fp.getDeletePostPermission() & Strings.AUTHOR_FORUM_DELETE_POST)!=0) )
		{
			int ans=Reactor.db.removeTopic(TopicID);
			if(ans!=-1)
			{
				return ans;
			}
			else
			{
				ErrorMsg="Cannot remove topic - Error in topic id";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Cannot remove topic - you haven't the right permissions or policy's reject";
			return -1;
		}
	}

	public static int addModerator(int userID, int SubForumID,
			TreeMap<String, String> session) {
		int flag;
		int subforumID=SubForumID;
		int forumID=Reactor.db.getParentForumID(subforumID);
		Forum forumForPolicy=Reactor.db.getForumByID(forumID);
		ForumPolicy fp=Reactor.db.getPolicyByID(forumForPolicy.getPolictyID());

		System.out.println("user ID: "+session.get("userID")+" subForumID: "+ subforumID+ " forum id: "+ forumID+" forumAdmin id "+Reactor.db.getForumByID(forumID).getAdminID());
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			int msgcount=getUserMsgCount(userID, session);

			if(fp.getAddModeratorPermission()==Strings.MIN_POST_ADD_MODERATOR)

			{
				if(msgcount>=Strings.MIN_POST_COUNT)
				{
					flag=Reactor.db.addModerateToSubForum(subforumID, userID); 	//  getSubForumByID(subforumID).AddModeratorId(userID);
					if(flag>0)
					{
						return 1;
					}
					else
					{
						ErrorMsg="Cannot add this moderator to this forum";
						return -1;
					}
				}
				else
				{
					ErrorMsg="Cannot add this moderator to this forum - Dont have enough messages";
					return -1;
				}
			}

			else if(fp.getAddModeratorPermission()==Strings.SENIORITY_ADD_MODERATOR)
			{
				User mod=Reactor.db.getUserByID(userID);
				int year=mod.getYear();
				int month=mod.getMonth();
				int day=mod.getDay();

				Calendar cal=Calendar.getInstance();
				cal.set(year, month, day);
				Calendar cal2=Calendar.getInstance();

				long diff = cal2.getTimeInMillis() - cal.getTimeInMillis();

				int days =(int) diff / (24 * 60 * 60 * 1000);

				if(days>=Strings.MIN_SENIORITY_DAYS)
				{
					flag=Reactor.db.addModerateToSubForum(subforumID, userID); 	//  getSubForumByID(subforumID).AddModeratorId(userID);
					if(flag>0)
					{
						return 1;
					}
					else
					{
						ErrorMsg="Cannot add this moderator to this forum";
						return -1;
					}
				}
				else
				{
					ErrorMsg="Cannot add this moderator to this forum - Seniority";
					return -1;
				}
			}
			else
			{
				ErrorMsg="Cannot add this moderator to this forum";
				return -1;
			}				


		}
		ErrorMsg="Cannot add this moderator to this forum - Permissions error";
		return -1;
	}



	public static int removeSubForum(int subForumID, TreeMap<String, String> session) {
		int forumID=Reactor.db.getParentForumID(subForumID);
		int flag;
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			flag=Reactor.db.removeSubForum(subForumID);
			if (flag>=0)
			{
				return 1;
			}
			else
			{
				ErrorMsg="Cannot remove this subforum - Error in db";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Permission error - Cannot remove sub forum";
			return -1;
		}
	}

	public static int removeModerator(int userID, int subforum,
			TreeMap<String, String> session) {
		SubForum sub=Reactor.db.getSubForumByID(subforum);
		int forumID=Reactor.db.getParentForumID(subforum);
		Forum forum = Reactor.db.getForumByID(forumID);
		ForumPolicy fp=Reactor.db.getPolicyByID(forum.getPolictyID());
		int flag;
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			if(sub.moderatorSize()==1)
			{
				if(fp.getRemoveModeratorPermission()==Strings.CAN_REMOVE_SINGLE_MODERATOR)
				{
					flag=Reactor.db.removeModeretor(userID, subforum);
					if (flag>=0)
					{
						return 1;
					}
					else
					{
						ErrorMsg="Cannot remove this subforum - Error in db";
						return -1;
					}
				}
				else
				{
					ErrorMsg="Cannot remove single moderator by policy";
					return -1;
				}
			}
			else
			{
				flag=Reactor.db.removeModeretor(userID, subforum);
				if (flag>=0)
				{
					return 1;
				}
				else
				{
					ErrorMsg="Cannot remove this subforum - Error in db";
					return -1;
				}
			}
		}
		else
		{
			ErrorMsg="You cannot remove moderator";
			return -1;
		}
	}

	public static int getSubForumSize(int subForumID,
			TreeMap<String, String> session) {
		Vector<Post> posts=Reactor.db.getSubForumPosts(subForumID);
		if(posts!=null)
		{
			return posts.size();
		}
		else
		{
			ErrorMsg="Cannot get size";
			return -1;
		}
	}

	public static int getUserMsgCount(int userID,
			TreeMap<String, String> session) 
	{
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		Vector<Post> userPosts=Reactor.db.getUserPosts(userID);
		if(userPosts!=null)
		{
			return userPosts.size();
		}
		else
		{
			ErrorMsg="Cannot get size";
			return -1;
		}
	}
		

	

	public static int getForumCount() {
		Vector<Forum> forumlist=Reactor.db.getForumlist();
		if(forumlist!=null)
		{
			return forumlist.size();
		}
		else
		{
			ErrorMsg="Cannot get size";
			return -1;
		}
	}

	public static Vector<String> getCommonUsers(TreeMap<String, String> session) {

		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && session.get("userID").equals(superAdminid))
		{
			Vector<String> userList=Reactor.db.getCommonUsernames();
			if(userList!=null)
			{
				return userList;
			}
			else
			{
				ErrorMsg="No common users";
				return null;
			}
		}
		else
		{
			ErrorMsg="You cannot do that";
			return null;
		}
	}

	public static Vector<String> getAllUsersThatReplyToID(int userID,
			TreeMap<String, String> session) {
		Vector<String> ans= new Vector<String>();
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && 
				(session.get("userID").equals(superAdminid)
						||
						Reactor.db.getForumByID(Reactor.db.getUserByID(userID).getForumIDRegisteredTo()).getAdminID()==Integer.parseInt(session.get("userID"))
						)
				)
		{
			Vector<User> userList=Reactor.db.getusersReplyToUserID(userID);
			if(userList!=null)
			{
				for (int i = 0; i < userList.size(); i++) {
					ans.add(userList.get(i).getUsername());
					ans.add(Integer.valueOf(userList.get(i).getId()).toString());
				}
				return ans;
			}
			else
			{
				ErrorMsg="No users";
				return null;
			}
		}
		else
		{
			ErrorMsg="You cannot do that";
			return null;
		}
	}

	public static Vector<String> getForumUsers(int forumID,
			TreeMap<String, String> session) {
		Vector<String> ans= new Vector<String>();
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";


		Vector<User> userList=Reactor.db.getUsers();

		for (int i = 0; i < userList.size(); i++) {
			if(userList.get(i).getForumIDRegisteredTo()==forumID)
			{
				ans.add(userList.get(i).getUsername());
				ans.add(Integer.valueOf(userList.get(i).getId()).toString());
			}
		}
		return ans;

	}

	public static int adminLogin(String username, String pass,
			TreeMap<String, String> session) {
		if(session.get("isOnline")!=null && session.get("isOnline").equals("true"))
		{
			ErrorMsg="Login error - You are is already logged in";
			return -1;
		}
		else if(Reactor.db.isUserExist2(username, pass))
		{
			int userID=Reactor.db.getUserByUserName(username).getId();
			session.put("isOnline", "true");
			session.put("userID", String.valueOf(Reactor.db.getUserByUserName(username).getId()));
			return Reactor.db.getUserByUserName(username).getId();

		}
		else
		{
			ErrorMsg="Login error - Wrong username or password";
			return -1;
		}

	}

	public static int addAdmin(int userID, int forumID,
			TreeMap<String, String> session) {
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && session.get("userID").equals(superAdminid))
		{
			int flag=Reactor.db.addAdmin(userID,forumID);
			if(flag!=-1)
			{
				return flag;
			}
			else
			{
				ErrorMsg="Cannot add this admin - Error in db";
				return -1;
			}
		}
		else
		{
			ErrorMsg="You cannot do that";
			return -1;
		}
	}

	public static int editReply(String replyBody, int replyID, TreeMap<String, String> session) {
		int TopicID;
		TopicID=Reactor.db.getReplyByID(replyID).getPostID();
		int subforumID=Reactor.db.getSubForumIdByTopicId(TopicID);
		int forumID=Reactor.db.getForumIdByTopicId(TopicID);
		Reply r=Reactor.db.getReplyByID(replyID);
		if(subforumID<=0 || forumID<= 0)
		{
			ErrorMsg="Reply not exists";
			return -1;
		}
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Reactor.db.getReplyByID(replyID).getUserID()==Integer.parseInt(session.get("userID"))
				||
				Reactor.db.isModerator(Integer.parseInt(session.get("userID")), subforumID)==1
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{

			if(r!=null)
			{
				Reactor.db.editReply(replyID, replyBody);
				return 1;
			}
			else
			{
				ErrorMsg="There is no reply with that id";
				return -1;
			}
		}
		else
		{
			ErrorMsg="No permissions";
			return -1;
		}
	}

	public static int editPost(String content, int postID, TreeMap<String, String> session) {

		int subforumID=Reactor.db.getSubForumIdByTopicId(postID);
		int forumID=Reactor.db.getForumIdByTopicId(postID);

		if(subforumID<=0 || forumID<= 0)
		{
			ErrorMsg="Post not exists";
			return -1;
		}

		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Reactor.db.getPostByID(postID).getUserID()==Integer.parseInt(session.get("userID"))
				||
				Reactor.db.getSubForumByID(Reactor.db.getSubForumIdByTopicId(postID)).isModeratorId(Integer.parseInt(session.get("userID")))
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			Post p=Reactor.db.getPostByID(postID);
			if(p!=null)
			{
				Reactor.db.editPost(postID, content);
				return postID;
			}
			else
			{
				ErrorMsg="There is no reply with that id";
				return -1;
			}
		}
		else
		{
			if(session.get("userID")!=null)
			{
				System.out.println("user id "+Integer.parseInt(session.get("userID")));
				System.out.println("subforum id : "+Reactor.db.getSubForumIdByTopicId(postID));
				Reactor.db.getSubForumByID(Reactor.db.getSubForumIdByTopicId(postID)).printModerators();
				System.out.println("is mod "+Reactor.db.getSubForumByID(Reactor.db.getSubForumIdByTopicId(postID)).isModeratorId(Integer.parseInt(session.get("userID"))));
			}
			ErrorMsg="No permissions";
			return -1;
		}
	}
	public static Forum getForumByReplyId(int replyID)
	{
		int postid= Reactor.db.getReplyByID(replyID).getPostID();
		int subForumid= Reactor.db.getPostByID(postid).getSubForumID();
		int forumid=Reactor.db.getSubForumByID(subForumid).getParentForum();
		return Reactor.db.getForumByID(forumid);
	}
	public static Post getPostByReplyID(int replyID)
	{
		int postid= Reactor.db.getReplyByID(replyID).getPostID();
		return Reactor.db.getPostByID(postid);
	}
	public static Vector<Integer> getRepliersOfPost(int postID)
	{
		Vector<Reply> r=Reactor.db.getPostReplies(postID);
		Vector<Integer> ans=new Vector<Integer>();
		Integer in;
		for (int i = 0; i < r.size(); i++) {
			in=new Integer(r.get(i).getUserID());
			ans.add(in);
		}
		return ans;
	}
	public static Vector<Integer> getForumUsers(int forumid)
	{
		Vector<User> v=Reactor.db.getUsers();
		Vector<Integer> ans=new Vector<Integer>();
		Integer in;
		for (int i = 0; i < v.size(); i++) {
			if(v.get(i).getForumIDRegisteredTo()==forumid)
			{
				in = new Integer(v.get(i).getId());
				ans.add(in);
				
			}
		}
		return ans;
	}

	public static int createPolicy(int whenNotify, int whoNotify, int howOften,  int deletePostPremission,
			int addModeratorPermission, int removeModeratorPermission, int securityPolicy, int badWordsPolicy, TreeMap<String, String> session) 
	{
		String superAdminid=Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()+"";
		if(session.get("userID")!=null && session.get("userID").equals(superAdminid))
		{
			int policyID=Reactor.db.addPolicy(whenNotify, whoNotify, howOften, deletePostPremission, addModeratorPermission, removeModeratorPermission, securityPolicy, badWordsPolicy);
			if(policyID!=-1)
			{
				return policyID;
			}
			else
			{
				ErrorMsg="Cannot add new policy to database";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Cannot add forum - not a super admin";
			return -1;
		}
	}

	public static Reply getReplyByID(int id) {
		// TODO Auto-generated method stub
		Reply r = Reactor.db.getReplyByID(id);
		return r;
	}

	public static User getUserByID(int editorID) {
		// TODO Auto-generated method stub
		User u = Reactor.db.getUserByID(editorID);
		return u;
	}

	public static Forum getForumByPostId(int id) {
		// TODO Auto-generated method stub
		int fid = Reactor.db.getForumIdByTopicId(id);
		Forum f = Reactor.db.getForumByID(fid);
		return f;
	}

	public static ForumPolicy getPolicyByForumId(int fid) {
		// TODO Auto-generated method stub
		Forum f = Reactor.db.getForumByID(fid);
		int PolicyID = f.getPolictyID();
		ForumPolicy fp = Reactor.db.getPolicyByID(PolicyID);
		return null;
	}

	public static Forum getForumById(int forumID) {
		Forum f = Reactor.db.getForumByID(forumID);
		return f;
	}

	public static int removeForum(int forumID, TreeMap<String, String> session) {
		int flag;
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{
			flag=Reactor.db.removeForum(forumID);
			if (flag>=0)
			{
				return 1;
			}
			else
			{
				ErrorMsg="Cannot remove this forum - Error in db";
				return -1;
			}
		}
		else
		{
			ErrorMsg="Permission error - Cannot remove sub forum";
			return -1;
		}
	}
	
	public static boolean isMailInUse(String mail, int forumID)
	{
		boolean ans=false;
		Vector<Integer> users=getForumUsers(forumID);
		for (int i = 0; i < users.size(); i++) 
		{
			if(getUserByID(users.get(i)).getMail().equals(mail))
			{
				return true;
			}
		}
		return ans;
	}

	public static int removeReply(int replyID, TreeMap<String, String> session) {
		int TopicID;
		Reply reply = Reactor.db.getReplyByID(replyID);
		if(reply == null)
		{
			ErrorMsg="invalid reply id";
			return -1;
		}
			
		TopicID=reply.getPostID();
		int subforumID=Reactor.db.getSubForumIdByTopicId(TopicID);
		int forumID=Reactor.db.getForumIdByTopicId(TopicID);
		Reply r=Reactor.db.getReplyByID(replyID);
		if(session.get("userID")!=null && 
				(Integer.parseInt(session.get("userID"))==Reactor.db.getForumByID(forumID).getAdminID() 
				||
				Reactor.db.getReplyByID(replyID).getUserID()==Integer.parseInt(session.get("userID"))
				||
				Reactor.db.isModerator(Integer.parseInt(session.get("userID")), subforumID)==1
				||
				Integer.parseInt(session.get("userID"))==Reactor.db.getUserByUserName(Reactor.db.getAdminUserName()).getId()))
		{

			if(r!=null)
			{
				Reactor.db.removeReply(replyID);
				return 1;
			}
			else
			{
				ErrorMsg="There is no reply with that id";
				return -1;
			}
		}
		else
		{
			ErrorMsg="No permissions";
			return -1;
		}
	}
	
	public static int activationReq(String username,
			String code, TreeMap<String, String> session) {
		int userID = -1;
		for (Iterator<Vector<String>> iterator = pendingUsers.iterator(); iterator.hasNext();) {
			Vector<String> user = (Vector<String>) iterator.next();
			if (user.get(0).equals(username) && user.get(4).equals(code)){
				userID=Reactor.db.addUser(user.get(0), user.get(1),user.get(2), Integer.parseInt(user.get(3)));
				pendingUsers.remove(user);
				break;
			}
		}
		if(userID!=-1)
		{
			return userID;
		}
		else
		{
			ErrorMsg="Code is incorrect";
			return userID;
		}
	}
	
	public static ForumPolicy getPolicyByID(int PolicyID)
	{
		return Reactor.db.getPolicyByID(PolicyID);
	}
	
	public static void InitForumNotifiers()
	{
		System.out.println("initForumNotifiers" );
		Vector<Forum> forumsList = Reactor.db.getForumlist();
		int PolicyID, fid;
		ForumNotifier fn;
		ForumPolicy p;
		
		for (int i = 0; i < forumsList.size(); i++) {
			fid = forumsList.get(i).getId();
			PolicyID = forumsList.get(i).getPolictyID();
			p = Reactor.db.getPolicyByID(PolicyID);
			fn = ForumNotifier.InitNotifier(fid, p.getHowOften());
			Thread t = new Thread(fn);
			t.start();
		}
		
	}
	public static Vector<String> get_subforum_moderators(int subForumID, TreeMap<String, String> session) {
		Vector<Integer> v = Reactor.db.getSubForumModerators(subForumID);
		Vector<String> ans=new Vector<String>();
		for (int i = 0; i < v.size(); i++) {
			ans.add(v.get(i).toString());
		}
		return ans;
	}
	public static void activateNotifier(ForumNotifier fn) {
		Thread t = new Thread(fn);
		t.start();
	}
	
	public static Post getPostByID(int postID)
	{
		return Reactor.db.getPostByID(postID);
	}
	

}
